#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>
/*
    一个简单的线程池demo
 */
int   pool_add_task(void *(*callback)(void *arg), void *arg);
void *thread_routine(void *arg);
/*
    线程池里所有运行和等待的任务都是一个thread_task
    由于所有任务都在链表里，所以是一个链表结构
*/
typedef struct task
{
    void *(*callback)(void *arg);  /*回调函数,任务运行时会调用此函数.*/
    void *arg;                     /*回调函数的参数*/
    struct task *next;
} thread_task;
typedef struct     /*线程池结构*/
{
    pthread_mutex_t queue_lock;   /*互斥锁*/
    pthread_cond_t queue_cond;    /*条件*/
    thread_task *tasks_head;      /*线程池中所有等待任务 链表*/
    int shutdown;                  /*是否销毁线程池*/
    pthread_t *threads_id;        /*线程池所有pthread_t*/
    int max_thread_num;           /*线程池中允许的活动线程数目*/
    int current_tasks_size;       /*当前等待队列的任务数目*/
} thread_pool;
static thread_pool *pool = NULL;
/*
    初始化线程池
*/
void pool_init(int max_thread_num)
{
    pool = (thread_pool *)malloc(sizeof(thread_pool));
    pthread_mutex_init(&(pool->queue_lock), NULL);
    pthread_cond_init(&(pool->queue_cond), NULL);
    pool->tasks_head = NULL;
    pool->max_thread_num = max_thread_num;
    pool->current_tasks_size = 0;
    pool->shutdown = 0;
    pool->threads_id =(pthread_t *)malloc(max_thread_num * sizeof (pthread_t));
    int i = 0;
    for (i = 0; i < max_thread_num; i++)
    {
        pthread_create(&(pool->threads_id[i]), NULL, thread_routine,NULL);
    }
}
/*
    向线程池中加入任务
*/
int pool_add_task(void *(*callback) (void *arg), void *arg)
{
    /*构造一个新任务*/
    thread_task *newtask =(thread_task *)malloc (sizeof (thread_task));
    newtask->callback = callback;
    newtask->arg = arg;
    newtask->next = NULL;    /*置空*/
    pthread_mutex_lock(&(pool->queue_lock));
    thread_task *task = pool->tasks_head;
    if (task != NULL)   /*将任务加入到等待队列中*/
    {
        while (task->next != NULL)
            task = task->next;
        task->next = newtask;
    }
    else
    {
        pool->tasks_head = newtask;
    }
    assert (pool->tasks_head != NULL);
    pool->current_tasks_size++;
    pthread_mutex_unlock (&(pool->queue_lock));
    /*唤醒一个等待线程;注意如果所有线程都在忙碌,这句没有任何作用*/
    //pthread_cond_broadcast()激活所有等待该条件的线程
    //pthread_cond_signal()激活一个等待该条件的线程
    pthread_cond_signal(&(pool->queue_cond));
    return 0;
}
/*
    销毁线程池，等待队列中的任务不会再被执行，
    但是正在运行的线程会一直把任务运行完后再退出
*/
int pool_destroy ()
{
    /*防止两次调用*/
    if(pool->shutdown) return -1;
    pool->shutdown = 1;
    /*唤醒所有等待线程，线程池要销毁了*/
    pthread_cond_broadcast (&(pool->queue_cond));
    int i;
    /*阻塞等待线程退出，否则就成僵尸了*/
    for(i = 0; i < pool->max_thread_num; i++)
        pthread_join(pool->threads_id[i], NULL);
    free(pool->threads_id);
    thread_task *head = NULL;
    while(pool->tasks_head != NULL)  /*销毁等待队列*/
    {
        head = pool->tasks_head;
        pool->tasks_head = pool->tasks_head->next;
        free(head);
    }
    /*条件变量和互斥量也要销毁*/
    pthread_mutex_destroy(&(pool->queue_lock));
    pthread_cond_destroy(&(pool->queue_cond));
    free (pool);
    pool=NULL;  /*销毁后指针置空是个好习惯*/
    return 0;
}
void * thread_routine (void *arg)
{
    printf ("[init thread 0x%x]\n", pthread_self ());
    while (1)
    {
        pthread_mutex_lock(&(pool->queue_lock));
        /*如果等待队列为0并且不销毁线程池，则处于阻塞状态; */
        while (pool->current_tasks_size == 0 && !pool->shutdown)
        {
            printf ("thread 0x%x is waiting\n", pthread_self ());
            //pthread_cond_wait无条件等待直到被激活
            //pthread_cond_timedwait及时等待
            //注意pthread_cond_wait是一个原子操作，等待前会解锁，唤醒后会加锁
            pthread_cond_wait(&(pool->queue_cond), &(pool->queue_lock));
        }
        /*线程池要销毁了*/
        if(pool->shutdown)
        {
            /*遇到break,continue,return等跳转语句，千万不要忘记先解锁*/
            pthread_mutex_unlock (&(pool->queue_lock));
            printf ("[destroy thread 0x%x]\n", pthread_self ());
            pthread_exit(NULL);
        }
        printf ("thread 0x%x is starting to work\n", pthread_self ());
        /*assert是调试的好帮手*/
        assert (pool->current_tasks_size != 0);
        assert (pool->tasks_head != NULL);
        /*等待队列长度减去1，并取出链表中的头元素*/
        pool->current_tasks_size--;
        thread_task *task = pool->tasks_head;
        pool->tasks_head = task->next;
        pthread_mutex_unlock (&(pool->queue_lock));
        (*(task->callback)) (task->arg); /*调用回调函数，执行任务*/
        free (task);
        task = NULL;
    }
    pthread_exit (NULL);
}
// 下面是测试代码
void *mycallback(void *arg)
{
    printf ("threadid is 0x%x, working on task %d\n", pthread_self (),*(int *)arg);
    sleep (1);/*休息一秒，延长任务的执行时间*/
    return NULL;
}
int main (int argc, char **argv)
{
    pool_init(4);/*线程池中最多三个活动线程*/
    /*连续向池中投入10个任务*/
    int args[10];
    
    int i;
    for (i = 0; i < 10; i++)
    {
        args[i] = i;
        pool_add_task(mycallback, &args[i]);
    }
    
    sleep(6);        /*等待所有任务完成 再销毁*/
    
    pool_destroy();  /*销毁线程池*/
    
    return 0;
}


